﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Runtime.Serialization;
using ActiveStoryTouch.DataModel;
using System.IO;
using System.Reflection;
using System.Windows.Ink;
using System.Collections.ObjectModel;
using ActiveStoryTouch.DataModel.Silverlight.Helpers;
using TouchToolkit.Framework;
using TouchToolkit.Framework.TouchInputProviders;
using TouchToolkit.GestureProcessor.Feedbacks.TouchFeedbacks;

namespace SilverlightWoZTouch
{
    public partial class MainPage : UserControl
    {
        private ASTDataModelServiceReference.ASTDataModelServiceClient _dataModelServiceClient = new ASTDataModelServiceReference.ASTDataModelServiceClient();
        private Guid _currentSessionId;
        private Page _currentPage;
        public MainPage()
        {
            InitializeComponent();
        }

        private void StartResume_Clicked(object sender, RoutedEventArgs e)
        {
            ASTDataModelServiceReference.ASTDataModelServiceClient client = new ASTDataModelServiceReference.ASTDataModelServiceClient();
            client.BeginSessionCompleted += new EventHandler<ASTDataModelServiceReference.BeginSessionCompletedEventArgs>(client_BeginSessionCompleted);
            client.BeginSessionAsync();
        }

        void client_BeginSessionCompleted(object sender, ASTDataModelServiceReference.BeginSessionCompletedEventArgs e)
        {
            MessageBox.Show(e.Result.ToString());
            ASTDataModelServiceReference.ASTDataModelServiceClient client = new ASTDataModelServiceReference.ASTDataModelServiceClient();
            client.GetInitialPageCompleted += new EventHandler<ASTDataModelServiceReference.GetInitialPageCompletedEventArgs>(client_GetInitialPageCompleted);
            client.GetInitialPageAsync(e.Result);
        }

        void client_GetInitialPageCompleted(object sender, ASTDataModelServiceReference.GetInitialPageCompletedEventArgs e)
        {
            MessageBox.Show(e.Result.Name);
        }

        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            InitGestureFramework();
            _dataModelServiceClient.GetPageWithIdCompleted += new EventHandler<ASTDataModelServiceReference.GetPageWithIdCompletedEventArgs>(dataModelServiceClient_GetPageWithIdCompleted);
            _dataModelServiceClient.BeginSessionCompleted += new EventHandler<ASTDataModelServiceReference.BeginSessionCompletedEventArgs>(dataModelServiceClient_BeginSessionCompleted);
            _dataModelServiceClient.BeginSessionAsync();
        }

        private void InitGestureFramework()
        {
            GestureFramework.Initialize(new SilverlightTouchInputProvider(), LayoutRoot, Assembly.GetExecutingAssembly());
            /* Add common visual feedbacks */
            //GestureFramework.AddTouchFeedback(typeof(BubblesPath));
        }

        void dataModelServiceClient_BeginSessionCompleted(object sender, ASTDataModelServiceReference.BeginSessionCompletedEventArgs e)
        {
            _currentSessionId = e.Result;
            _dataModelServiceClient.GetInitialPageCompleted += new EventHandler<ASTDataModelServiceReference.GetInitialPageCompletedEventArgs>(dataModelServiceClient_GetInitialPageCompleted);
            _dataModelServiceClient.GetInitialPageAsync(_currentSessionId);
        }

        void dataModelServiceClient_GetInitialPageCompleted(object sender, ASTDataModelServiceReference.GetInitialPageCompletedEventArgs e)
        {
            _currentPage = e.Result;
            RenderPage(_currentPage, MainInkPresenter);
        }

        void RenderPage(Page pageToRender, InkPresenter targetInkPresenter)
        {
            ClearPage();
            StrokeCollection strokes = StrokeHelper.ConvertToStrokeCollection(pageToRender.Strokes);
            foreach (Stroke item in strokes)
            {
                targetInkPresenter.Strokes.Add(item);
            }

            foreach (PrototypeElement item in pageToRender.PrototypeElementDictionary.Values)
            {
                FrameworkElement elementToAdd = null;
                switch (item.ElementType)
                {
                    case ElementTypes.None:
                        break;
                    case ElementTypes.Button:
                        elementToAdd = new Canvas { Background =  App.Current.Resources["ButtonGradientBrush"] as Brush };
                        break;
                    case ElementTypes.TextBox:
                        break;
                    case ElementTypes.ListBox:
                        break;
                    case ElementTypes.RadioButton:
                        break;
                    case ElementTypes.CheckBox:
                        break;
                    case ElementTypes.Label:
                        break;
                    default:
                        break;
                }


                elementToAdd.Width = double.IsNaN(item.Width) ? 50 : item.Width;
                elementToAdd.Height = double.IsNaN(item.Height) ? 30 : item.Height;
                InkPresenter.SetTop(elementToAdd, item.Top);
                InkPresenter.SetLeft(elementToAdd, item.Left);
                // TODO: Apply other properties of prototypeelement

                targetInkPresenter.Children.Add(elementToAdd);


                foreach (var gestureItem in item.GestureTargetPageMap)
                {
                    if (gestureItem.Key.ToLower().Equals("tap"))
                    {
                        (elementToAdd as Canvas).MouseLeftButtonUp += new MouseButtonEventHandler(delegate(object sender, MouseButtonEventArgs e)
                        {
                            NavigateToPageWithId(gestureItem.Value);
                        });
                    }
                    else
                    {
                        GestureFramework.EventManager.AddEvent(elementToAdd, gestureItem.Key,
                            delegate(UIElement sender, GestureEventArgs e)
                            {
                                NavigateToPageWithId(gestureItem.Value);
                            });
                    }
#if DEBUG
                    // TODO: The following is only here for testing purposes! Move to proper location once testing starts on touch device.

                    //(elementToAdd as Canvas).MouseLeftButtonUp += new MouseButtonEventHandler(delegate(object sender, MouseButtonEventArgs e)
                    //{
                    //    NavigateToPageWithId(gestureItem.Value);
                    //});
#endif
                }
            }
        }

        private void ClearPage()
        {
            if (MainInkPresenter != null)
            {
                MainInkPresenter.Children.Clear();
                MainInkPresenter.Strokes.Clear();
            }
        }

        private void NavigateToPageWithId(long pageId)
        {
            _dataModelServiceClient.GetPageWithIdAsync(_currentSessionId, pageId);
        }

        private void dataModelServiceClient_GetPageWithIdCompleted(object sender, ASTDataModelServiceReference.GetPageWithIdCompletedEventArgs e)
        {
            _currentPage = e.Result;
            RenderPage(e.Result, MainInkPresenter);
        }

        #region Old test code
        //private void button1_Click(object sender, RoutedEventArgs e)
        //{
        //    OpenFileDialog ofd = new OpenFileDialog();
        //    if (!ofd.ShowDialog().GetValueOrDefault(false))
        //        return;
        //    FileStream fs = ofd.File.OpenRead();
        //    DataContractSerializer seriazlier = new DataContractSerializer(typeof(SerializableStrokeCollection));
        //    Object o = seriazlier.ReadObject(fs);
        //    SerializableStrokeCollection sc = o as SerializableStrokeCollection;
        //    fs.Close();

        //    StrokeCollection newStrokeCollection = new StrokeCollection();

        //    foreach (var stroke in sc)
        //    {
        //        DrawingAttributes drawingAttr = new DrawingAttributes { Color = stroke.DrawingAttributes.Color, Height = stroke.DrawingAttributes.Height, Width = stroke.DrawingAttributes.Width };
        //        StylusPointCollection spc = new StylusPointCollection();
        //        foreach (var stylusPoint in stroke.StylusPoints)
        //        {
        //            StylusPoint sp = new StylusPoint { X = stylusPoint.X, Y = stylusPoint.Y, PressureFactor = stylusPoint.PressureFactor };
        //            spc.Add(sp);
        //        }
        //        Stroke newStroke = new Stroke(spc);
        //        newStroke.DrawingAttributes = drawingAttr;
        //        inkPresenter1.Strokes.Add(newStroke);
        //    }
            
        //}

        //private void Button_Click(object sender, RoutedEventArgs e)
        //{
        //    ASTDataModelServiceReference.ASTDataModelServiceClient client = new ASTDataModelServiceReference.ASTDataModelServiceClient();
        //    client.TestStrokeSendingCompleted += new EventHandler<ASTDataModelServiceReference.TestStrokeSendingCompletedEventArgs>(client_TestStrokeSendingCompleted);
        //    client.TestStrokeSendingAsync();
        //}

        //void client_TestStrokeSendingCompleted(object sender, ASTDataModelServiceReference.TestStrokeSendingCompletedEventArgs e)
        //{
        //    ObservableCollection<SerializableStroke> sc = e.Result;

        //    foreach (var stroke in sc)
        //    {
        //        DrawingAttributes drawingAttr = new DrawingAttributes { Color = stroke.DrawingAttributes.Color, Height = stroke.DrawingAttributes.Height, Width = stroke.DrawingAttributes.Width };
        //        StylusPointCollection spc = new StylusPointCollection();
        //        foreach (var stylusPoint in stroke.StylusPoints)
        //        {
        //            StylusPoint sp = new StylusPoint { X = stylusPoint.X, Y = stylusPoint.Y, PressureFactor = stylusPoint.PressureFactor };
        //            spc.Add(sp);
        //        }
        //        Stroke newStroke = new Stroke(spc);
        //        newStroke.DrawingAttributes = drawingAttr;
        //        inkPresenter1.Strokes.Add(newStroke);
        //    }
        //}
        #endregion
    }
}
